`ifndef DUAL_RAM_V
`define DUAL_RAM_V


`include "defines.v"

// 解决了读写冲突的实际的 ram
module dual_ram #(
    parameter DATA_WIDTH = 32,
    parameter ADDR_WIDTH = 12,
    parameter MEM_NUM    = 4096
)
(
    input  wire                     clk,
    input  wire                     rstn,
    input  wire                     wen,
    input  wire[ADDR_WIDTH - 1 : 0] waddr_i,
    input  wire[DATA_WIDTH - 1 : 0] wdata_i,
    input  wire                     ren,
    input  wire[ADDR_WIDTH - 1 : 0] raddr_i,
    output reg[DATA_WIDTH - 1 : 0]  rdata_o
);

reg                         r_equal_w_flag;
reg[DATA_WIDTH - 1 : 0]     wdata_reg;
wire[DATA_WIDTH - 1 : 0]    rdata_wire;

assign rdata_o = r_equal_w_flag ? wdata_i : rdata_wire;

// 满足读时序，第二拍读的时候数据仍然存在
always @(posedge clk or negedge rstn) begin
    if(rstn == 1'b0) begin
        wdata_reg <= 32'd0;
    end
    else begin
        wdata_reg <= wdata_i;
    end
end

always @(posedge clk or negedge rstn) begin
    if(rstn == 1'b0) begin
        r_equal_w_flag <= 1'b0;
    end
    else if(rstn && wen && ren && (raddr_i == waddr_i)) begin
        r_equal_w_flag <= 1'b1;
    end
    else begin
        r_equal_w_flag <= 1'b0;
    end
end

dual_ram_template #(
    .DATA_WIDTH (DATA_WIDTH),
    .ADDR_WIDTH (ADDR_WIDTH),
    .MEM_NUM    (MEM_NUM)
) u_dual_ram_template(
    .clk        (clk),
    .rstn       (rstn),
    .wen        (wen),
    .waddr_i    (waddr_i),
    .wdata_i    (wdata_i),
    .ren        (ren),
    .raddr_i    (raddr_i),
    .rdata_o    (rdata_wire)
);

endmodule

// 存在读写冲突的原始 ram
module dual_ram_template #(
    parameter DATA_WIDTH = 32,
    parameter ADDR_WIDTH = 12,
    parameter MEM_NUM    = 4096
)
(
    input  wire                     clk,
    input  wire                     rstn,
    input  wire                     wen,
    input  wire[ADDR_WIDTH - 1 : 0] waddr_i,
    input  wire[DATA_WIDTH - 1 : 0] wdata_i,
    input  wire                     ren,
    input  wire[ADDR_WIDTH - 1 : 0] raddr_i,
    output reg[DATA_WIDTH - 1 : 0]  rdata_o
);

reg[DATA_WIDTH - 1 : 0] memory[0 : MEM_NUM - 1];

// 读
always @(posedge clk or negedge rstn) begin
    if(rstn == 1'b0) begin
        rdata_o <= 32'h0000_0000;
    end
    else if(ren == 1'b1) begin
        rdata_o <= memory[raddr_i];
    end
end

// 写
always @(posedge clk or negedge rstn) begin
    if(rstn == 1'b0) begin

    end
    else if(wen == 1'b1) begin 
        memory[waddr_i] <= wdata_i;
    end
end

endmodule


`endif // DUAL_RAM_V